﻿using Common.Contract;
using Common.Contract.Authentication.Record;
using Common.Contract.Customer;
using Common.Contract.Customer.Record;
using Common.Contract.Customer.Request;
using Common.Contract.Paging;
using Common.Contract.Warranty.Request;
using Common.Contract.Warranty.Response;
using Common.Service;
using Common.Service.Command;
using Common.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Warranty.Model.Interface;
using Warranty.Model.Model;

namespace Warranty.ServiceCommand
{
    public class SearchPeriodInquiryServiceCommand : ProviderServiceCommand<IProviderFactory, SearchPeriodInquiryRequest, SearchPeriodInquiryResponse>
    {
        public SearchPeriodInquiryServiceCommand(IProviderFactory provider) : base(provider) { }

        protected override void Validate(SearchPeriodInquiryRequest request)
        {
            if (request == null) throw new ArgumentNullException("request");
            if (!request.Header.ApplicationKey.HasValue || request.Header.ApplicationKey == Guid.Empty)
            {
                throw new ArgumentException("ApplicationKey must be set", "request");
            }
        }

        protected override bool OnExecute(SearchPeriodInquiryResponse response)
        {
            bool isSuccess = true;
            string errorMessage = string.Empty;
            int pageSize = 0, pageIndex = 0, totalRecord = 0;
            List<PeriodInquiryRecord> records = new List<PeriodInquiryRecord>();
            var applicationKey = Request.Header.ApplicationKey;
            if (Request.Page != null)
            {
                pageIndex = Request.Page.PageIndex ?? 0;
                pageSize = Request.Page.PageSize ?? 0;
            }

            var warantyMasterTemps = Providers.WarrantyMessage.Search(Request.SerialNumber, Request.Model, Request.TransferFlag).Select(i1 => new WarrantyMaster
            {
                SerialNo = i1.SerialNo,
                Model = i1.Model,
                CreateDate = i1.CreateDate,
                StartDate = i1.StartDate,
                EndDate = i1.EndDate,
                EndUserCell = i1.EndUserCell,
                ShopCell = string.Empty,
            }).ToList();

            var warantyMasterItems = Providers.WarrantyMaster.Search(Request.SerialNumber, Request.Model);
            warantyMasterItems.AddRange(warantyMasterTemps);
            var groupItems = (from x in warantyMasterItems
                              group x by new { x.Model, x.SerialNo, x.EndUserCell, x.ShopCell } into g
                              select new
                              {
                                  SerialNo = g.First().SerialNo,
                                  Model = g.First().Model,
                                  ReceiveDate = g.Max(y => y.CreateDate),
                                  StartDate = g.Min(y => y.StartDate),
                                  EndDate = g.Min(x => x.EndDate),
                                  EndUserCell = g.First().EndUserCell,
                                  ShopCell = g.First().ShopCell
                              }).Distinct().ToList();

            Dictionary<string, ModelCatRecord> modelCats = new Dictionary<string, ModelCatRecord>();
            using (ServiceClient<ICustomer> serviceClient = new ServiceClient<ICustomer>())
            {
                SearchModelCatRequest requestShops = new SearchModelCatRequest
                {
                    Header = new RequestHeaderRecord
                    {
                        ApplicationKey = Request.Header.ApplicationKey,
                        CallerName = "Warranty.ServiceCommand.SearchPeriodInquiryServiceCommand"
                    },
                    Model = Request.Model
                };

                var responseShops = serviceClient.Proxy.SearchModelCat(requestShops);
                if (responseShops.IsSuccess) modelCats = responseShops.Records.ToDictionary(x => x.Model);
            }

            if (groupItems != null) records = groupItems.Where(x => modelCats.ContainsKey(x.Model)).Select((x) =>
            {
                var item = new PeriodInquiryRecord
                    {
                        EndDate = x.EndDate,
                        EndUserCell = x.EndUserCell,
                        Model = x.Model,
                        Product = modelCats[x.Model].ProdL1,
                        RemainDay = (x.EndDate.HasValue && x.StartDate.HasValue) ? (decimal)(x.EndDate.Value - x.StartDate.Value).TotalDays : 0,
                        RequestDate = x.ReceiveDate,
                        SerialNumber = x.SerialNo,
                        ShopCell = x.ShopCell,
                        StartDate = x.StartDate,
                        Suffix = modelCats[x.Model].Suffix
                    };
                return item;
            }).ToList();

            if (!Request.TextSearch.IsNullOrWhiteSpace())
            {
                var textsearch = Request.TextSearch.Trim().ToUpper();
                records = records.Where(x => x.Model.ToUpper().Contains(textsearch) ||
                                             x.Product.ToUpper().Contains(textsearch) ||
                                             x.SerialNumber.ToUpper().Contains(textsearch) ||
                                             x.ShopCell.ToUpper().Contains(textsearch) ||
                                             x.EndUserCell.ToUpper().Contains(textsearch) ||
                                             x.Suffix.ToUpper().Contains(textsearch)).ToList();
            }

            totalRecord = records.Count;
            if (pageSize > 0 && pageIndex >= 0)
            {
                records = records.Skip(pageIndex * pageSize).Take(pageSize).ToList();
            }
            response.Records = records;
            response.Page = new PageRecord
            {
                PageIndex = pageIndex,
                PageSize = pageSize,
                TotalRecords = totalRecord
            };
            return isSuccess;
        }
    }
}
